/*
 *
 * Copyright (c) 2008, Felix Bruns <felixbruns@web.de>
 *
 */

function Cache(){
	/* Database or array */
	this.cache = [];

	/* Google gears is available */
	this.gears = false;

	/* Google gears */
	if(typeof(window.google) != 'undefined' && typeof(google.gears) != 'undefined'){
		/* Set variable */
		this.gears = true;

		/* Create database object */
		this.cache = google.gears.factory.create('beta.database');

		/* Open cache database */
		this.cache.open('lastfm.cache');

		/* Create cache table */
		this.cache.execute('CREATE TABLE IF NOT EXISTS cache (hash VARCHAR(40) PRIMARY KEY, data TEXT, expiration INTEGER);');
	}

	var CachePolicy = function(){
		var MINUTE =          60;
		var HOUR   = MINUTE * 60;
		var DAY    = HOUR   * 24;
		var WEEK   = DAY    *  7;
		var MONTH  = WEEK   *  4.34812141;
		var YEAR   = MONTH  * 12;

		var weeklyMethods = [
			'artist.getSimilar',
			'tag.getSimilar',
			'track.getSimilar',
			'artist.getTopAlbums',
			'artist.getTopTracks',
			'geo.getTopArtists',
			'geo.getTopTracks',
			'tag.getTopAlbums',
			'tag.getTopArtists',
			'tag.getTopTags',
			'tag.getTopTracks',
			'user.getTopAlbums',
			'user.getTopArtists',
			'user.getTopTags',
			'user.getTopTracks'
		];

		var weeklyChartsExpiration = WEEK;

		this.getExpirationTime = function(params){
			var method = params.method;

			if((/Weekly/).test(method) && /List/.test(method) == false){
				if(typeof(params.to) != 'undefined' && typeof(params.from) != 'undefined'){
					return YEAR;
				}
				else{
					return weeklyChartsExpiration;
				}
			}

			for(var key in weeklyMethods){
				if(method == weeklyMethods[key]){
					return WEEK;
				}
			}

			return -1;
		};

		this.setWeeklyChartsExpiration = function(expiration){
			weeklyChartsExpiration = expiration;
		};
	};

	var policy = new CachePolicy();

	this.getPolicy = function(){
		return policy;
	}

	this.contains = function(hash){
		if(this.gears){
			var result = this.cache.execute("SELECT 1 FROM cache WHERE hash = ? LIMIT 1;", [hash]);

			if(result.isValidRow() && result.field(0) == 1){
				result.close();

				return true;
			}

			return false;
		}
		else{
			return typeof(this.cache[hash]) != 'undefined';
		}
	}

	this.load = function(hash){
		if(this.gears){
			var result = this.cache.execute("SELECT data FROM cache WHERE hash = ? LIMIT 1;", [hash]);
			var data   = {};

			if(result.isValidRow()){
				data = result.field(0);

				result.close();
			}

			return data;
		}
		else{
			return this.cache[hash];
		}
	}

	this.remove = function(hash){
		if(this.gears){
			this.cache.execute("DELETE FROM cache WHERE hash = ? LIMIT 1;", [hash]);
		}
		else{
			this.cache[hash] = undefined;
		}
	}

	this.store = function(hash, data, expiration){
		if(this.gears){
			var time = Math.round(new Date().getTime() / 1000);

			this.cache.execute('INSERT OR REPLACE INTO cache VALUES(?, ?, ?);', [hash, data, time + expiration]);
		}
		else{
			this.cache[hash] = data;
		}
	}

	this.isExpired = function(hash){
		if(this.gears){
			var result = this.cache.execute("SELECT expiration FROM cache WHERE hash = ? LIMIT 1;", [hash]);
			var time   = Math.round(new Date().getTime() / 1000);

			if(result.isValidRow() && time > result.field(0)){
				result.close();

				return true;
			}

			return false;
		}
		else{
			return false;
		}
	}

	this.clear = function(){
		if(this.gears){
			this.cache.execute('DELETE FROM cache');
		}
		else{
			this.cache = [];
		}
	}

	this.hasGoogleGears = function(){
		return this.gears;
	}
}
